#include "UI.h"
#include "RS232.h"
#include "../ACUAS/projectdefinitions.h"

#include <stdio.h>

void
ui_initialize()
{
  lcd_init(LCD_DISP_ON);

  // Define special character "Heart"
  LCDcharDef(1, 0x00, 0x1B, 0x1F, 0x1F, 0x0E, 0x04, 0x00, 0x00);
  // Define special character "Diamond"
  LCDcharDef(2, 0x04, 0x0E, 0x1F, 0x1F, 0x1F, 0x0E, 0x04, 0x00);
  // Define special character "Club"
  LCDcharDef(3, 0x0E, 0x0E, 0x04, 0x1F, 0x1F, 0x04, 0x04, 0x0E);
  // Define special character "Spade"
  LCDcharDef(4, 0x00, 0x04, 0x0E, 0x1F, 0x1F, 0x1F, 0x04, 0x0E);
  // Define special character "Full_Case"
  LCDcharDef(5, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F);
  // Define special character "LINE_LEFT"
  LCDcharDef(6, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F);
  // Define special character "LINE_RIGHT"
  LCDcharDef(7, 0x1F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F);
  // Define special character "LINE_UP_DOWN"
  LCDcharDef(8, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F);
}

char
ui_is_button_down(char button)
{
  return !(PINA & (1 << button));
}

static void
ui_draw_card(Card card)
{
  static const unsigned char suites[] = { 0, 0, 1, 2, 3 };
  static const unsigned char values[] =
    { 0, 'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K' };

  // Get card suite and value
  unsigned char suite = card_get_suite(card);
  unsigned char value = card_get_value(card);

  // Check if the card is valid
  if (suite == 0 || value == 0)
    return;

  lcd_putc(values[value]);
  lcd_putc(suites[suite]);
}

static void
ui_draw_hand(Hand *hand, unsigned char hide_cards)
{
  unsigned char i;
  for (i = 0; i < 5; i++) {
    if (i != 0)
      lcd_putc(' ');

    Card card = (*hand)[i];
    if (card == 0)
      break;

    if (hide_cards == 0 || i == 0)
      ui_draw_card(card);
    else
      lcd_puts("??");
  }
}

static void
ui_draw_hands(Hand *player, Hand *dealer, unsigned char hide_cards)
{
  lcd_gotoxy(0, 0);
  lcd_puts("P ");
  ui_draw_hand(player, 0);

  lcd_gotoxy(0, 1);
  lcd_puts("D ");
  ui_draw_hand(dealer, hide_cards);

  char buffer[20];
  lcd_gotoxy(0, 2);
  if (hide_cards)
    sprintf(buffer, "%u", hand_get_score(player));
  else
    sprintf(buffer, "%u vs %u",
            hand_get_score(player), hand_get_score(dealer));

  lcd_puts("Score: ");
  lcd_puts(buffer);
}

static void
ui_draw_progress_bar(unsigned char percent)
{
  lcd_putc(percent > 5 ? 4 : 5);
  lcd_putc(percent > 15 ? 4 : 7);
  lcd_putc(percent > 25 ? 4 : 7);
  lcd_putc(percent > 35 ? 4 : 7);
  lcd_putc(percent > 45 ? 4 : 7);
  lcd_putc(percent > 55 ? 4 : 7);
  lcd_putc(percent > 65 ? 4 : 7);
  lcd_putc(percent > 75 ? 4 : 7);
  lcd_putc(percent > 85 ? 4 : 7);
  lcd_putc(percent > 95 ? 4 : 6);
}

static void
ui_draw_percentage(unsigned char percent)
{
  char buffer[6];
  sprintf(buffer, "%u", percent);
  lcd_puts(buffer);
  lcd_putc('%');
}

void
ui_shuffling(Card card, unsigned char percent)
{
  lcd_clrscr();

  lcd_gotoxy(0, 1);
  lcd_puts(" Shuffling ");

  ui_shuffling_update(card, percent);
}

void
ui_shuffling_update(Card card, unsigned char percent)
{
  lcd_gotoxy(11, 1);
  ui_draw_card(card);
  lcd_gotoxy(1, 2);
  ui_draw_progress_bar(percent);
  lcd_putc(' ');
  ui_draw_percentage(percent);
}

unsigned int
ui_get_bet(unsigned int maximum)
{
  char buffer[20];

  // Initial bet suggestion is 100 chips
  unsigned int value = 100;
  if (value > maximum)
    value = maximum;

  unsigned char client_counter = 0;

  lcd_clrscr();

  lcd_gotoxy(0, 0);
  sprintf(buffer, "%u", maximum);
  lcd_puts(buffer);
  lcd_puts(" Chips left");

  lcd_gotoxy(0, 1);
  lcd_puts("Place bet please");

  while (1) {
    // Show current selection
    lcd_gotoxy(1, 3);
    sprintf(buffer, ">%u<", value);
    lcd_puts(buffer);
    lcd_puts(" Chips");

    // Wait for previously pressed buttons to be released
    while (ui_is_button_down(4) ||
           ui_is_button_down(6)) delay_ds(1);

    // Wait until next relevant button is pressed
    while (!ui_is_button_down(0) &&
           !ui_is_button_down(4) &&
           !ui_is_button_down(6)) {
      unsigned int response = rs232_get_bet(maximum, client_counter == 0 ? 1 : 0);
      if (response != 0)
        return response;

      client_counter = (client_counter + 1) % 10;
    }


    // If "Enter" was pressed
    if (ui_is_button_down(0)) {
      while (ui_is_button_down(0)) delay_ds(1);
      break;
    }

    // If "Down" was pressed
    if (ui_is_button_down(4)) {
      value -= 100;

      if (value < 100)
        value = 100;

      continue;
    }

    // If "Up" was pressed
    if (ui_is_button_down(6)) {
      value += 100;

      if (value > maximum)
        value = maximum;

      continue;
    }
  }

  // Return the chosen bet
  return value;
}

unsigned char
ui_hit_or_stand(Hand *player, Hand *dealer)
{
  unsigned char value = 1;
  unsigned char client_counter = 0;

  lcd_clrscr();

  ui_draw_hands(player, dealer, 1);

  while (1) {
    // Show current selection
    lcd_gotoxy(1, 3);
    lcd_putc(value ? '>' : ' ');
    lcd_puts("Hit");
    lcd_putc(value ? '<' : ' ');
    lcd_puts("  ");
    lcd_putc(!value ? '>' : ' ');
    lcd_puts("Stand");
    lcd_putc(!value ? '<' : ' ');

    // Wait for previously pressed buttons to be released
    while (ui_is_button_down(5) ||
           ui_is_button_down(7)) delay_ds(1);

    // Wait until next relevant button is pressed
    while (!ui_is_button_down(0) &&
           !ui_is_button_down(5) &&
           !ui_is_button_down(7)) {
      unsigned char response = rs232_hit_or_stand(player, client_counter == 0 ? 1 : 0);
      if (response != 0)
        return response - 1;

      client_counter = (client_counter + 1) % 10;
    }

    // If "Enter" was pressed
    if (ui_is_button_down(0)) {
      while (ui_is_button_down(0)) delay_ds(1);
      break;
    }

    // If "Right" was pressed
    if (ui_is_button_down(5)) {
      value = 0;
      continue;
    }

    // If "Left" was pressed
    if (ui_is_button_down(7)) {
      value = 1;
      continue;
    }
  }

  return value;
}

void
ui_round_result(Hand *player, Hand *dealer, unsigned char result)
{
  unsigned char client_counter = 0;

  lcd_clrscr();

  ui_draw_hands(player, dealer, 0);

  lcd_gotoxy(0, 3);
  if (result == 2)
    lcd_puts("Player wins!");
  else if (result == 1)
    lcd_puts("Nobody wins!");
  else
    lcd_puts("Dealer wins!");

  // Wait until "Enter" button is pressed
  while (!ui_is_button_down(0)) {
    if (rs232_skip_screen(client_counter == 0 ? 1 : 0) != 0)
      return;

    client_counter = (client_counter + 1) % 10;
  }

  while (ui_is_button_down(0)) delay_ds(1);
}

void
ui_game_over()
{
  unsigned char client_counter = 0;

  lcd_clrscr();

  lcd_gotoxy(0, 1);
  lcd_puts("   Game over!");

  lcd_gotoxy(0, 3);
  lcd_puts("  >Play again<");

  // Wait until "Enter" button is pressed
  while (!ui_is_button_down(0)) {
    if (rs232_skip_screen(client_counter == 0 ? 1 : 0) != 0)
      return;

    client_counter = (client_counter + 1) % 10;
  }

  while (ui_is_button_down(0)) delay_ds(1);
}

unsigned char
ui_scores(GameScore score)
{
  unsigned char value = 1;
  unsigned char client_counter = 0;

  char buffer[20];
  lcd_clrscr();

  lcd_gotoxy(0, 0);
  sprintf(buffer, "%u/%u", score.Wins, score.Rounds);
  lcd_puts("Wins:  ");
  lcd_puts(buffer);

  lcd_gotoxy(0, 1);
  sprintf(buffer, "%u", score.Chips);
  lcd_puts("Chips: ");
  lcd_puts(buffer);

  while (1) {
    // Show current selection
    lcd_gotoxy(0, 3);
    lcd_putc(' ');
    lcd_putc(value ? '>' : ' ');
    lcd_puts("Play");
    lcd_putc(value ? '<' : ' ');
    lcd_putc(' ');
    lcd_putc(!value ? '>' : ' ');
    lcd_puts("Reset");
    lcd_putc(!value ? '<' : ' ');
    lcd_putc(' ');

    // Wait for previously pressed buttons to be released
    while (ui_is_button_down(5) ||
           ui_is_button_down(7)) delay_ds(1);

    // Wait until next relevant button is pressed
    while (!ui_is_button_down(0) &&
           !ui_is_button_down(5) &&
           !ui_is_button_down(7)) {
      if (rs232_skip_screen(client_counter == 0 ? 1 : 0) != 0)
        return 1;

      client_counter = (client_counter + 1) % 10;
    }

    // If "Enter" was pressed
    if (ui_is_button_down(0)) {
      while (ui_is_button_down(0)) delay_ds(1);
      break;
    }

    // If "Right" was pressed
    if (ui_is_button_down(5)) {
      value = 0;
      continue;
    }

    // If "Left" was pressed
    if (ui_is_button_down(7)) {
      value = 1;
      continue;
    }
  }

  return value;
}
